﻿Imports VPager.My.Resources

Namespace Settings

    Public Class SettingsManager

        Private Shared mInstance As SettingsManager
        Private Shared mLock As New Object
        Private mSettings As Hashtable = New Hashtable
        Private mNeedsCommit As Boolean = False
        Private mStore As SettingsStore

        Public Event SettingValueChanged(ByVal sender As SettingsManager, ByVal e As SettingEventArgs)

        Public ReadOnly Property Count As Integer
            Get
                Return mSettings.Count
            End Get
        End Property

        Public ReadOnly Property NeedsSaving As Boolean
            Get
                Return mNeedsCommit
            End Get
        End Property

        Public ReadOnly Property ConfigFile As String
            Get
                Return mStore.ConfigFile
            End Get
        End Property

        Protected Sub New()

            ' -------------------------------------------------------------------------
            ' Install Numeric Based Settings
            ' -------------------------------------------------------------------------
            '
            Dim numStg As NumberSetting

            ' TRANSITION_TIME
            ' Number of seconds to take to transition between slides 
            '   Fade Out and Fade In times are each half of this value
            numStg = installNumberSetting(
                SettingKey.TRANSITION_TIME, STG_TRANSITION_TIME_NAME,
                STG_TRANSITION_TIME_DESC, STG_TRANSITION_TIME_DEFAULT)
            numStg.LowerBound = 0
            numStg.UpperBound = 2
            numStg.AllowDecimal = True

            ' LOG_LEVEL
            ' Minimum priorty level at which to log messages
            numStg = installNumberSetting(
                SettingKey.LOG_LEVEL, STG_LOG_LEVEL_NAME,
                STG_LOG_LEVEL_DESC, STG_LOG_LEVEL_DEFAULT)
            numStg.LowerBound = 1
            numStg.UpperBound = 5

            ' PAGE_PAUSE
            ' Number of seconds to display current page code before showing next code
            numStg = installNumberSetting(
                SettingKey.PAGE_PAUSE, STG_PAGE_PAUSE_NAME,
                STG_PAGE_PAUSE_DESC, STG_PAGE_PAUSE_DEFAULT)
            numStg.LowerBound = 0
            numStg.AllowDecimal = True

            ' MARK_TIME
            ' Duration in seconds between writing a MARK statements in the log
            '   Log Marks are used to identify the system is running
            numStg = installNumberSetting(
                SettingKey.MARK_TIME, STG_MARK_TIME_NAME,
                STG_MARK_TIME_DESC, STG_MARK_TIME_DEFAULT)
            numStg.LowerBound = 1

            ' PING_TIMEOUT
            ' Number of seconds before Ping test times out for Network Test
            numStg = installNumberSetting(
                SettingKey.PING_TIMEOUT, STG_PING_TIMEOUT_NAME,
                STG_PING_TIMEOUT_DESC, STG_PING_TIMEOUT_DEFAULT)
            numStg.LowerBound = 0

            ' PING_FREQUENCY
            ' Number of seconds between pings for Network Testing
            numStg = installNumberSetting(
                SettingKey.PING_FREQUENCY, STG_PING_FREQUENCY_NAME,
                STG_PING_FREQUENCY_DESC, STG_PING_FREQUENCY_DEFAULT)
            numStg.LowerBound = 1

            ' NET_ALARM_THRESHOLD
            ' Number of seconds of continuous ping failures before setting status to ERROR
            numStg = installNumberSetting(
                SettingKey.NET_ALARM_THRESHOLD, STG_NET_ALARM_NAME,
                STG_NET_ALARM_DESC, STG_NET_ALARM_DEFAULT)
            numStg.LowerBound = 1

            ' -------------------------------------------------------------------------
            ' Install Simple Text Based Settings
            ' -------------------------------------------------------------------------
            '
            ' LOG_FILE
            ' The path to the log file. File is appended to it exists, otherwise it is created.
            installTextSetting(
                SettingKey.LOG_FILE, STG_LOG_FILE_NAME,
                STG_LOG_FILE_DESC, STG_LOG_FILE_DEFAULT)

            ' PAGER_FILE
            ' The path to the text file used to read active page codes from
            installTextSetting(
                SettingKey.PAGER_FILE, STG_PAGER_FILE_NAME,
                STG_PAGER_FILE_DESC, STG_PAGER_FILE_DEFAULT)

            ' PING_TARGETS
            ' Comma seperated string of host names to ping for Network Test
            installTextSetting(
                SettingKey.PING_TARGETS, STG_PING_TARGETS_NAME,
                STG_PING_TARGETS_DESC, STG_PING_TARGETS_DEFAULT)


            ' Setup Persistance Store (Read/Write to file)
            mStore = New SettingsStore(mSettings)

        End Sub

        Public Shared Function getInstance() As SettingsManager
            '
            ' Prevents multiple threads from creating
            ' separate instances
            '
            SyncLock mLock
                '
                ' initialize object if it hasn't already been done
                '
                If mInstance Is Nothing Then
                    mInstance = New SettingsManager
                End If
                '
                ' return the initialized instance
                '
                Return mInstance
            End SyncLock
        End Function

        Public Shared Function getValue(ByVal key As SettingKey) As Object
            Return CType(getInstance.mSettings.Item(key), BaseSetting).Value
        End Function

        Private Function installNumberSetting(ByVal id As SettingKey,
                                              ByVal name As String,
                                              ByVal desc As String,
                                              ByVal defValue As String) As NumberSetting
            Dim ntb = New NumberSetting(id, name, desc, defValue)
            AddHandler ntb.ValueChanged, AddressOf settingValueChangedHandler
            mSettings.Add(ntb.ID, ntb)

            Return ntb
        End Function

        Private Sub installTextSetting(ByVal id As SettingKey,
                                        ByVal name As String,
                                        ByVal desc As String,
                                        ByVal defvalue As Object)
            Dim lts = New TextSetting(id, name, desc, defvalue)
            AddHandler lts.ValueChanged, AddressOf settingValueChangedHandler
            mSettings.Add(lts.ID, lts)

        End Sub

        Public Function getEnumerator() As IEnumerator
            Return mSettings.Values.GetEnumerator
        End Function

        Public Sub save()
            For Each entry As DictionaryEntry In mSettings
                CType(entry.Value, BaseSetting).commit()
            Next
            mStore.save()
            mNeedsCommit = False
        End Sub

        Private Sub settingValueChangedHandler(ByVal sender As BaseSetting, ByVal e As SettingEventArgs)
            mNeedsCommit = True
            onSettingChanged(e)
        End Sub

        Private Sub onSettingChanged(ByVal e As SettingEventArgs)
            RaiseEvent SettingValueChanged(Me, e)
        End Sub

        Sub cancelChanges()
            For Each entry As DictionaryEntry In mSettings
                CType(entry.Value, BaseSetting).rollback()
            Next
            mNeedsCommit = False
        End Sub

    End Class

    ' Inner Class To Handle Event Args
    Public Class SettingEventArgs
        Inherits EventArgs

        Private mSetting As BaseSetting
        Private mOldValue As Object

        Public ReadOnly Property Setting As BaseSetting
            Get
                Return mSetting
            End Get
        End Property

        Public ReadOnly Property OldValue As Object
            Get
                Return mOldValue
            End Get
        End Property

        Public Sub New(ByVal setting As BaseSetting, ByVal oldVal As Object)
            MyBase.New()
            mSetting = setting
            mOldValue = oldVal
        End Sub

    End Class
End Namespace
